﻿using System;
using System.Data;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ComClassLibrary;
using Path = System.IO.Path;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Xml.Linq;
using LogLib;
using SoftKeyBoard;
using KeyboardArg;

namespace SelectionKeyBoard
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// 输入参数
        /// </summary>
        private KeyBoardArgs _keyboardArg;

        public KeyBoardArgs KeyboardArgs
        {
            get { return _keyboardArg; }
        }

        public MainWindow()
        {
            InitializeComponent();
        }

        public MainWindow(KeyBoardArgs KeyBoardArgs)
        {
            InitializeComponent();
            SetKeyBoardArg(KeyBoardArgs);
        }

        /// <summary>
        /// 窗口隐藏事件
        /// </summary>
        public event EventHandler Hidden;

        protected void OnWndHidden()
        {
            if (Hidden != null)
            {
                Hidden(this, new EventArgs());
            }
        }


        /// <summary>
        /// 选择级数
        /// </summary>
        private int _totalLevel = 0;
        /// <summary>
        /// 当前级数
        /// </summary>
        private int _currentLevel = 1;
      
        private DataSet _dataSetSrc = new DataSet();
        private int _btnHeight = 23;
        private int _btnWidth = 64;
        private int _btnHorDistance = 5; //水平间距
        private int _btnVerDistance = 5; //垂直间距
        private int _btnHorOffSet = 0;   //水平偏移
        private int _btnVerOffSet = 0;   //垂直偏移 
        private int _btnFontSize = 10;   //垂直偏移 
        private string _curSeletedValue = "";
        private List<XButton> _listButtons = new List<XButton>();
        private List<XLabel> _listLabels = new List<XLabel>();
        private bool _isCustomDesignUI = false;
        private Dictionary<string, string> NameToAdressMap = new Dictionary<string, string>();

        /// <summary>
        /// 当前页面显示的文字元素和对应键值
        /// </summary>
        List<KeyValuePair<string, string>> listShowKeyValues = new List<KeyValuePair<string, string>>();

        /// <summary>
        /// 对于多级选项，保存当前选中的根元素名称
        /// </summary>
        private List<string> ListSelectedLevels = new List<string>();

        public void SetLocation(System.Drawing.Rectangle rect)
        {
            // 计算窗体在屏幕上的位置，使其位于屏幕中心
            int x = rect.Left + (rect.Width - (int)this.Width) / 2;
            int y = rect.Top + (rect.Height - (int)this.Height) / 2;

            // 设置窗体的位置
            this.Left = x;
            this.Top = y;
        }

        public bool SetKeyBoardArg(KeyBoardArgs args)
        {
            _keyboardArg = args;
            _currentLevel = 1;
            ListSelectedLevels.Clear();
            _totalLevel = 0;
           
            //读配置文件
            string exeDir = System.AppDomain.CurrentDomain.BaseDirectory;
            string xmlFileName = "";
            string iniFileName = "";
            string uiConfigFile = "";
            string langCode = _keyboardArg.LanguageCode;
            if (string.IsNullOrEmpty(_keyboardArg.LanguageCode))
            {
                langCode = "zh-CN";
            }
          
            xmlFileName = string.Format("{0}\\DIC\\{1}\\{2}.xml", exeDir, langCode, _keyboardArg.DictionaryFileName);
            iniFileName = string.Format("{0}\\DIC\\{1}\\{2}.ini", exeDir, langCode, _keyboardArg.DictionaryFileName);
            uiConfigFile = string.Format("{0}\\DIC\\{1}\\{2}_UI.xml", exeDir, langCode, _keyboardArg.DictionaryFileName);          
         
            if (!File.Exists(xmlFileName) || !File.Exists(iniFileName))
            {
                MessageBox.Show("字典文件" + xmlFileName + "不存在");
                return false;
            }
            if (File.Exists(uiConfigFile))
            {
                _isCustomDesignUI = true;
            }
            else
            {
                _isCustomDesignUI = false;
            }
          
            _dataSetSrc = new DataSet();
            _dataSetSrc.ReadXml(xmlFileName);
            _totalLevel = _dataSetSrc.Tables.Count;
            if (_totalLevel <= 0)
            {
                return false;
            }

            // 如果加载小区映射文件
            if (_keyboardArg.DictionaryFileName.Equals("StandardAddress"))
            {
                LoadAdressMap(xmlFileName);
            }

            for (int i = 0; i < _dataSetSrc.Tables.Count; i++)
            {
                int rowCount = _dataSetSrc.Tables[i].Rows.Count;
            }

            if (_isCustomDesignUI)
            {
                if (!ReadUIConfig(uiConfigFile))
                {
                    return false;
                }
            }

            LoadCfg(iniFileName);
            if (!string.IsNullOrEmpty(_keyboardArg.Title))
            {
                lblTips.Content = _keyboardArg.Title;
            }
            CreatSelectButtons();
            return true;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
               
        }

        private bool ReadUIConfig(string fileName)
        {
            UIConfig config = new UIConfig(fileName);
            if (!config.OnReading())
            {
                MessageBox.Show("读取配置文件" + fileName + "失败: " + config.Error);
                return false;
            }
            _listButtons = config.ListButtons;
            _listLabels = config.ListLabels;
            return true;
        }

        private void LoadCfg(string fileName)
        {
            //string str = IniFile.IniValue("setting", "Title", "", fileName);;
            string titleValue = IniFile.IniValue("setting", "Title", "", fileName);
            string titleFileName = string.Format("{0}\\{1}", Path.GetDirectoryName(fileName), titleValue);
            if (File.Exists(titleFileName))
            {
                lblTips.Content = ReadTitle(titleFileName);
            }
            else
            {
                lblTips.Content = titleValue;
            }
            _btnHeight = int.Parse(IniFile.IniValue("setting", "ButtonHeight", "23", fileName));
            _btnWidth = int.Parse(IniFile.IniValue("setting", "ButtonWidtht", "64", fileName));
            _btnHorDistance = int.Parse(IniFile.IniValue("setting", "ButtonHorDistance", "5", fileName));
            _btnVerDistance = int.Parse(IniFile.IniValue("setting", "ButtonVerDistance", "5", fileName));
            _btnHorOffSet = int.Parse(IniFile.IniValue("setting", "ButtonHorOffSet", "0", fileName));
            _btnVerOffSet = int.Parse(IniFile.IniValue("setting", "ButtonVerOffSet", "0", fileName));
            _btnFontSize = int.Parse(IniFile.IniValue("setting", "ButtonFontSize", "10", fileName));
        }

        private bool HasChild()
        {
            if (string.IsNullOrEmpty(_curSeletedValue) || _curSeletedValue.Length == 0)
            {
                return false;
            }
            if (_curSeletedValue.Length == 1)
            {
                return false;
            }
            if (_curSeletedValue.Length <= (2 * (_currentLevel - 1)))
            {
                return false;
            }
            return true;
        }

        private void GetShowKeys(int level)
        {
            listShowKeyValues.Clear();
            DataRow[] drs;          
            if (level > 1)
            {
                drs = _dataSetSrc.Tables[level].Select(string.Format("value like '{0}%'", _curSeletedValue.Substring(0, 2 * (level - 1))));
            }
            else
            {
                drs = _dataSetSrc.Tables[level].Select("");
            }
            foreach (DataRow dr in drs)
            {
                string key = dr["key"].ToString();
                string value = dr["value"].ToString();
                listShowKeyValues.Add(new KeyValuePair<string, string>(key, value));
            }
        }

        private bool CreatSelectButtons()
        {
            GetShowKeys(_currentLevel);
            if (listShowKeyValues == null || listShowKeyValues.Count == 0)
            {
                return false;
            }
            if (_isCustomDesignUI)
            {
                return CreatCustomButtons() && CreatCustomLabels();
            }
            else
            {
                return CreatDefaultButtons();
            }
        }

        private bool CreatDefaultButtons()
        {
            try
            {
                int maxHeight = 0;
                canButtons.Children.Clear();
                int i = 0;
                int curBtnVerticalHeight = 0;//按钮当前垂直高度
                foreach (KeyValuePair<string, string> p in listShowKeyValues)
                {
                    TextBlock tb = new TextBlock()
                    {
                        Text = p.Key,                       
                        FontSize = _btnFontSize,
                        TextWrapping = TextWrapping.Wrap,
                        TextAlignment = TextAlignment.Center
                    };
                    Button btn = new Button
                    {
                        Name = "button" + "_" + p.Value,
                        Content = tb,
                        Height = _btnHeight,
                        Width = _btnWidth,
                        HorizontalAlignment = HorizontalAlignment.Left,
                        Margin = new Thickness(10, 10, 0, 0),
                        VerticalAlignment = VerticalAlignment.Top,
                        Visibility = Visibility.Visible,
                        FontSize = _btnFontSize,
                        Background = Brushes.LightSkyBlue
                    };          
       
                    btn.Click += new RoutedEventHandler(btn_click);
                    canButtons.Children.Add(btn);
                    double canvasLeft = (double)(i * (_btnWidth + _btnHorDistance));
                    if ((int)canvasLeft + _btnWidth + 5 > SelectionArea.Width)  //超出容器，另外起一行
                    {
                        i = 0;
                        curBtnVerticalHeight += (_btnVerDistance + _btnHeight);
                        canvasLeft = (double)(i * (_btnWidth + _btnHorDistance));
                    }
                    btn.SetValue(Canvas.LeftProperty, canvasLeft+(int)_btnHorOffSet);
                    btn.SetValue(Canvas.TopProperty, (double)(curBtnVerticalHeight+_btnVerOffSet));
 					if (maxHeight < curBtnVerticalHeight + _btnVerOffSet)
                    {
                        maxHeight = curBtnVerticalHeight + _btnVerOffSet;
                    }
                    i++;
                }
				 if (maxHeight < 800)
                    canButtons.Height = 800;
                else
                    canButtons.Height = 3 * _btnHeight + maxHeight;
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
                Console.WriteLine(e);
                return false;
            }
        }

        private bool CreatCustomButtons()
        {
            try
            {
                canButtons.Children.Clear();
                for (int i = 0; i < listShowKeyValues.Count; i++)
                {
                    KeyValuePair<string, string> p = listShowKeyValues[i];
                    string Name = "button" + "_" + p.Value.ToString();
                    XButton xBtn = _listButtons.Find(r => r.Name.Equals(Name));
                    if (xBtn != null)
                    {
                        Button btn = xBtn.Creat(canButtons);
                        if (btn != null)
                        {
                            btn.Click += new RoutedEventHandler(btn_click);
                        }    
                    }
                }
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
                return false;
            }
        }

        private bool CreatCustomLabels()
        {
            if(_listLabels == null || _listLabels.Count == 0)
            {
                return true;
            }
            try
            {
                for (int i = 0; i < _listLabels.Count; i++)
                {                
                    XLabel xLabel = _listLabels[i];
                    if (xLabel != null)
                    {
                        Label btn = xLabel.Creat(canButtons);                      
                    }
                }
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
                return false;
            }
        }

        private void btn_click(object sender, RoutedEventArgs e)
        {
            scrollViewer1.ScrollToTop(); //结束后滚到最上面
            Button btn = (Button)sender;
            if (_currentLevel == 1 && ListSelectedLevels.Count == 1)
            {
                ListSelectedLevels[0] = ((TextBlock)btn.Content).Text;
            }
            else
            {
                ListSelectedLevels.Add(((TextBlock)btn.Content).Text);    
            }
            _currentLevel++;     
            _curSeletedValue = btn.Name.Split('_')[1];           
            if (_currentLevel < _totalLevel && HasChild())            
            {
                if (CreatSelectButtons())
                {
                    return;
                }
            }

            // 获取返回参数
            UpdateKeyboardArgs(btn);

            //点到最后一级后，发消息回主窗体，并且隐藏窗体
            _keyboardArg.Command = "OK";
            SendMessage();
            this.Hide();
            OnWndHidden();
        }

        private void UpdateKeyboardArgs(Button btn)
        {
            //获取按钮的值
            string key = ((TextBlock)btn.Content).Text;
            string value = "";
            string[] array = btn.Name.Split('_');
            if (array.Length != 2)
            {
                MessageBox.Show("获取键值失败, 请检查字典配置是否正确.");
            }
            else
            {
                value = array[1];
            }            
            _keyboardArg.PassageType = SendMessageType.Response;
             _keyboardArg.Content = key;
            KeyValuePair<string, string> p = listShowKeyValues.Find(r => r.Key.Equals(key));
            if (!string.IsNullOrEmpty(p.Value))
            {
                _keyboardArg.Code = p.Value;
            }
            else
            {
                _keyboardArg.Code = value;
            }           
            if (null != btn.Tag)
            {
                _keyboardArg.Tag = btn.Tag.ToString();
            }
            GetFullContent();
        }

        private void GetFullContent()
        {
            _keyboardArg.FullContent = "";
            if (_keyboardArg.DictionaryFileName.Equals("ShiXian") || _keyboardArg.DictionaryFileName.Equals("StayPlace")) // 籍贯，省市县
            {
                if (ListSelectedLevels.Count == 3)
                {
                    if (ListSelectedLevels[2].EndsWith("县") || ListSelectedLevels[2].EndsWith("旗"))
                    {
                        _keyboardArg.FullContent += ListSelectedLevels[0] + ListSelectedLevels[2];
                    }
                    else
                    {
                        foreach (string val in ListSelectedLevels)
                        {
                            _keyboardArg.FullContent += val;
                        }
                    }
                }
                else
                {
                    foreach (string val in ListSelectedLevels)
                    {
                        _keyboardArg.FullContent += val;
                    }
                }
                return;
            }
           
            foreach (string val in ListSelectedLevels)
            {
                _keyboardArg.FullContent += val;
            }

            if (_keyboardArg.DictionaryFileName.Equals("StandardAddress"))
            {
                string key = ListSelectedLevels[0];
                if (NameToAdressMap.ContainsKey(key))
                {
                    _keyboardArg.FullContent = NameToAdressMap[key] + _keyboardArg.FullContent;
                }
            }
        }

        private bool SendMessage()
        {
            scrollViewer1.ScrollToTop(); //结束后滚到最上面
            if (_keyboardArg.MsgReceiver == IntPtr.Zero)
            {
                MessageBox.Show("句柄错误", "句柄错误");
                return false;
            }
            int uMsg = (int)MessageType.WM_COPYDATA;   
            string strMsgText = JsonHandler.ConvertToJsonString(_keyboardArg);          
            byte[] data = System.Text.Encoding.UTF8.GetBytes(strMsgText);
            COPYDATASTRUCT_INTPTR cds = new COPYDATASTRUCT_INTPTR();
            cds.dwData = (IntPtr)uMsg;
            cds.cbData = data.Length;
            cds.lpData = Marshal.AllocHGlobal(data.Length);
            Marshal.Copy(data, 0, cds.lpData, data.Length);
            Message.SendMessage(_keyboardArg.MsgReceiver, uMsg, 0, ref cds);
            cds.Free();
            return true;
        }

        public string ReadTitle(string path)
        {
            StreamReader sr = new StreamReader(path, Encoding.UTF8);
            string ret = "";
            string line = "";
            while ((line = sr.ReadLine()) != null)
            {
                ret+=line;
            }
            return ret;
        }

        private void buttonClose_Click(object sender, RoutedEventArgs e)
        {
            scrollViewer1.ScrollToTop(); //结束后滚到最上面
            if (_keyboardArg == null)
            {
                this.Hide();
                OnWndHidden();
                return;
            }
            int uMsg = (int)MessageType.WM_COPYDATA;
            _keyboardArg.PassageType = SendMessageType.Response;
            _keyboardArg.Content = "";
            _keyboardArg.Command = "Cancel";
            string strMsgText = JsonHandler.ConvertToJsonString(_keyboardArg);          
            byte[] data = System.Text.Encoding.UTF8.GetBytes(strMsgText);
            COPYDATASTRUCT_INTPTR cds = new COPYDATASTRUCT_INTPTR();
            cds.dwData = (IntPtr)uMsg;
            cds.cbData = data.Length;
            cds.lpData = Marshal.AllocHGlobal(data.Length);
            Marshal.Copy(data, 0, cds.lpData, data.Length);
            Message.SendMessage(_keyboardArg.MsgReceiver, uMsg, 0, ref cds);
            cds.Free();
            this.Hide();
            OnWndHidden();
            return;
        }

        private void buttonBackToLast_Click(object sender, RoutedEventArgs e)
        {
            if (_currentLevel == 1)
                return;
            if (_currentLevel > 1)
            {
                _currentLevel--;
                ListSelectedLevels.RemoveAt(ListSelectedLevels.Count - 1);
                CreatSelectButtons();
            }
        }

        /// <summary>
        /// 加载小区地址的映射表
        /// </summary>
        private void LoadAdressMap(string xmlFile)
        {
            try
            {
                XDocument xmlDoc = XDocument.Load(xmlFile);
                XElement root = xmlDoc.Element("root");
                if (root == null)
                    return;
                NameToAdressMap.Clear();
                IEnumerable<XElement> elems = root.Elements("Level1");
                foreach (XElement e in elems)
                {
                    string key = e.Attribute("key").Value.Trim();
                    string roadName = e.Attribute("RoadName").Value.Trim();
                    string houseNumber = e.Attribute("HouseNumber").Value.Trim();
                    string adress = roadName + houseNumber + "号";
                    NameToAdressMap.Add(key, adress);
                }
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());   
            }         
        }
    }
}
